package entorno;

public class MonitorPetri {
	//Atributos
	private int [] estadoActual;
	private int [][] matrizIncidencia;
	
	SemaforoBinario mutex = new SemaforoBinario(1);
	CVSemaforo cond = new CVSemaforo(mutex);
	
	public MonitorPetri(int[][] matriz, int[] condicionInicial){
        super();
        this.matrizIncidencia = matriz;
        this.estadoActual = condicionInicial;
    }

	
	//Sumar dos vectores
    private int[] sumaVectores(int A[], int B[]){
        int [] resultado = new int [A.length];
	
        if ((A.length == B.length)){
            for (int i = 0; i<A.length; i++){
            	resultado [i] = A[i] + B[i];
            }
            return resultado;
        }
        else{
        	return null;
        }
    }
    
    //Multiplicar una matriz por un vector
    private int [] multiplicacionMatrizVector(int matriz[][], int vector[]){
        int resultado[] = new int [matriz.length]; 
        int suma = 0;

		if ((matriz[0].length == vector.length)){
            for(int i = 0; i <matriz.length; i++){
                suma = 0;
                for (int j = 0; j < matriz[0].length; j++ ){
                	suma = suma + matriz[i][j] * vector[j];
                }
                resultado[i] = suma;
            }
            return resultado;
		}
		else{
			return null;
		}
    }
    
    private void actualizarEstado(int[] nuevoEstado){
    	estadoActual = nuevoEstado;
    }
    
    private int[] calculaNuevoEstado(int[] trans){
    	int[] Aux;
    	Aux = multiplicacionMatrizVector(matrizIncidencia, trans);	
    	if(Aux!=null){
    	return sumaVectores(estadoActual, Aux);
    	}else{
    		System.out.println("Error en multiplicacionMatrizVector");
    		return estadoActual;
    	}
    	
    }
    
	public boolean dispararTransicion(int transicion []){
		mutex.WAIT();
		
		int[] pruebaNuevoEstado;
		boolean disparo = true;
		
		pruebaNuevoEstado = this.calculaNuevoEstado(transicion);
		
    	for (int k=0; k<pruebaNuevoEstado.length; k++){
    			if (pruebaNuevoEstado[k]<0)
    			{
    				disparo = false;
    				break;
    			}
    	}
    	
    	if (disparo == true){
    		this.actualizarEstado(pruebaNuevoEstado);
    		
//    		System.out.print("Vector: ");
//    		for(int i=0;i<pruebaNuevoEstado.length;i++){
//    			System.out.print(pruebaNuevoEstado[i]);
//    		}
//    		System.out.print("\n");
    		
    	}
//		cond.RESUME();
		mutex.SIGNAL();
		return disparo;
	}
	
	public boolean consultarTransicion(int transicion []){
		mutex.WAIT();
		
		int[] pruebaNuevoEstado;
		boolean disparo = true;
		
		pruebaNuevoEstado = this.calculaNuevoEstado(transicion);
		
    	for (int k=0; k<pruebaNuevoEstado.length; k++){
    			if (pruebaNuevoEstado[k]<0)
    			{
    				disparo = false;
    				break;
    			}
    	}
    	

//		cond.RESUME();
		mutex.SIGNAL();
		return disparo;
	}
}
